package com.newly.center.business.service.impl;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.newly.api.sys.feign.AuthEntityClient;
import com.newly.center.business.service.CheckRecordService;
import com.newly.center.business.service.CompanyService;
import com.newly.center.business.service.SiteService;
import com.newly.common.base.constants.AuthConstant;
import com.newly.common.base.constants.CommonConstant;
import com.newly.common.base.entity.R;
import com.newly.common.base.entity.auth.ICurrentTenant;
import com.newly.common.base.entity.business.Dto.CheckRecordDto;
import com.newly.common.base.entity.business.Dto.SiteDto;
import com.newly.common.base.entity.business.Po.CheckRecord;
import com.newly.common.base.entity.business.Po.Company;
import com.newly.common.base.entity.business.Po.Site;
import com.newly.common.base.entity.business.Vo.CheckRecordVo;
import com.newly.common.base.entity.business.Vo.DetailsVo;
import com.newly.common.base.entity.business.Vo.RecordVo;
import com.newly.common.base.entity.device.po.DevicePo;
import com.newly.common.base.exception.NewlyException;
import com.newly.common.core.utils.CopyUtil;
import com.newly.common.core.utils.PageUtil;
import com.newly.common.core.utils.RequestUtils;
import com.newly.common.mapper.business.SiteMapper;
import com.newly.common.mapper.sys.AuthEntityMapper;
import com.newly.common.mapper.sys.DeviceMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @anthor sbq
 * @date 2021/10/26 14:25O
 */
@Service("siteService")
public class SiteServiceImpl extends ServiceImpl<SiteMapper, Site> implements SiteService {

    @Autowired
    private CompanyService companyService;
    @Autowired
    private AuthEntityMapper entityMapper;
    @Autowired
    private DeviceMapper deviceMapper;
    @Autowired
    private CheckRecordService checkRecordService;

    @Autowired
    private AuthEntityClient authEntityClient;

    @Autowired
    private SiteMapper siteMapper;

    @Autowired
    private RequestUtils requestUtils;

    @Override
    public PageUtil getPage(ICurrentTenant currentTenant, SiteDto siteDto) {
        List<Site> siteList;
        Page<Site> page = new Page<>(siteDto.getPageNum(), siteDto.getPageSize());
        //获取数据范围
        List<String> entityIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.SITE);
        if (ObjectUtil.isEmpty(entityIds)) return new PageUtil(page);

        List<Company> companyList = this.companyService.list(new QueryWrapper<Company>().lambda()
                .like(StringUtils.isNotBlank(siteDto.getCompanyName()), Company::getName, siteDto.getCompanyName()));
        if (ObjectUtil.isEmpty(companyList)) return new PageUtil(page);

        List<Long> companyIds = companyList.stream().map(Company::getId).collect(Collectors.toList());
        QueryWrapper<Site> q = new QueryWrapper<>();
        q.lambda().eq(StringUtils.isNotBlank(siteDto.getId()), Site::getId, siteDto.getId());
        q.lambda().like(StringUtils.isNotBlank(siteDto.getName()), Site::getName, siteDto.getName());
        q.lambda().eq(siteDto.getType() != null, Site::getType, siteDto.getType());
        q.lambda().in(Site::getCompanyId, companyIds);
        q.lambda().in(Site::getId, entityIds);
        q.lambda().eq(Site::getIsDeleted, 0);
        //分页查询
        page = this.page(page, q);
        if (page.getRecords().isEmpty())
            return new PageUtil(page);
        siteList = page.getRecords();
        List<Long> siteIds = siteList.stream().map(Site::getId).collect(Collectors.toList());
        //设置企业名称
        siteList = siteList.stream().map(p -> companyList.stream().filter(m ->
                Objects.equals(p.getCompanyId(), m.getId())).findFirst()
                .map(m -> {
                    p.setCompanyName(m.getName());
                    return p;
                }).orElse(p))
                .filter(Objects::nonNull)
                .collect(Collectors.toList());
        page.setRecords(siteList);
        return new PageUtil(page);
    }

    @Override
    public DetailsVo<Site> getDetailsById(Long id, Integer offset) {

        String startTime = DateUtil.offsetDay(DateUtil.date(), -offset).toString();
        DetailsVo<Site> detailsVo = new DetailsVo<>();
        Site site = this.getOne(new QueryWrapper<Site>().lambda().eq(Site::getId, id).eq(Site::getIsDeleted, 0));
        Company company = this.companyService.getOne(new QueryWrapper<Company>().lambda().eq(Company::getId, site.getCompanyId()).eq(Company::getIsDeleted, 0));
        site.setCompanyName(ObjectUtil.isEmpty(company) ? "" : company.getName());
        detailsVo.setEntity(site);
        CheckRecordDto checkRecordDto = new CheckRecordDto().setSiteIds(Arrays.asList(id)).setStartTime(startTime).setEndTime(DateUtil.now());
        List<CheckRecord> checkRecordList = this.checkRecordService.getListByCondition(checkRecordDto);
        List<CheckRecordVo> checkRecordVoList = CopyUtil.copyList(checkRecordList, CheckRecordVo.class);
        checkRecordVoList = this.checkRecordService.cover(checkRecordVoList);
        List<RecordVo> recordVos = new ArrayList<>();
        for (CheckRecordVo checkRecordVo : checkRecordVoList) {
            RecordVo recordVo = new RecordVo()
                    .setId(checkRecordVo.getId())
                    .setSiteName(checkRecordVo.getSiteName())
                    .setRatio(checkRecordVo.getOverRate())
                    .setOverweightType(checkRecordVo.getOverweightType())
                    .setTime(new DateTime(checkRecordVo.getCreateTime()).toString());
            recordVos.add(recordVo);
        }
        detailsVo.setRecordVoList(recordVos);
        return detailsVo;
    }

    @Override
    public void edit(Site site) {

        Company company = this.companyService.getOne(new QueryWrapper<Company>().lambda().eq(Company::getName, site.getCompanyName()).eq(Company::getIsDeleted, 0));
        site.setCompanyId(company.getId());
        site.setCreateTime(DateUtil.now());
        updateById(site);
    }

    @Override
    public void insert(Site site) {

        Company company = this.companyService.getOne(new QueryWrapper<Company>().lambda().eq(Company::getName, site.getCompanyName()).eq(Company::getIsDeleted, 0));
        site.setCompanyId(company.getId());
        site.setCreateTime(DateUtil.now());
        this.save(site);

        // 绑定权限实体
    /*    AuthEntityPo authEntityPo = new AuthEntityPo();
        authEntityPo.setEntityId(site.getId().toString());
        authEntityPo.setType(EntityTypeEnum.站点.getCode());
        authEntityPo.setCreateTime(DateUtil.date());
        this.entityMapper.insert(authEntityPo);*/
        authEntityClient.bind(AuthConstant.AuthEntityType.SITE,
                ListUtil.toLinkedList(site.getId().toString()));
    }

    @Override
    public R delete(Long[] ids) {
        List<Site> siteList = this.list(new QueryWrapper<Site>().lambda().in(Site::getId, Arrays.asList(ids)));
        if (siteList.size() == 0)
            throw new NewlyException("站点id有误，请联系管理员！");
        List<DevicePo> devicePoList = this.deviceMapper.selectList(new LambdaQueryWrapper<DevicePo>().in(DevicePo::getSiteId, Arrays.asList(ids)).eq(DevicePo::getIsDeleted, 0));
        if (devicePoList.size() > 0)
            return R.fail(1, "站点存在设备，不能删除！");
        List<CheckRecord> checkRecordList = this.checkRecordService.list(new LambdaQueryWrapper<CheckRecord>().in(CheckRecord::getSiteId, Arrays.asList(ids)));
        if (checkRecordList.size() > 0)
            return R.fail(1, "站点存在监测记录，不能删除！");
        siteList = siteList.stream().peek(t -> t.setIsDeleted(1)).collect(Collectors.toList());
        this.updateBatchById(siteList);
        //删除权限实体对应记录
       /* List<AuthEntityPo> entityPos = this.entityMapper.selectList(new QueryWrapper<AuthEntityPo>().lambda().in(AuthEntityPo::getEntityId, Arrays.asList(ids)));
        if (ObjectUtil.isEmpty(entityPos))
            throw new NewlyException("站点id没有绑定到权限实体表，请联系管理员！");
        List<Integer> entityIds = entityPos.stream().map(AuthEntityPo::getId).collect(Collectors.toList());
        this.entityMapper.deleteBatchIds(entityIds);*/
        return R.ok(0);
    }

    @Override
    public List<String> getSiteNames() {
        ICurrentTenant currentTenant = requestUtils.getCurrentTenant();
        List<String> entityIds = currentTenant.getEntityIds(AuthConstant.AuthEntityType.SITE);
        if (ObjectUtil.isEmpty(entityIds)) return null;

        List<Site> siteList = this.list(new QueryWrapper<Site>().lambda()
                .in(Site::getId, entityIds)
                .eq(Site::getIsDeleted, 0).orderByAsc(Site::getId));
        return siteList.stream().map(Site::getName).collect(Collectors.toList());
    }

    public List<Map<String, Object>> getSiteNameAndId() {
        List<Site> siteList = this.list(new QueryWrapper<Site>().lambda().eq(Site::getIsDeleted, 0).orderByAsc(Site::getId));
        HashMap<String, Object> collect = siteList.stream().collect(HashMap::new,
                (m, c) -> {
                    m.put(c.getName() + "", c.getId() + "");
                }, HashMap::putAll);

        List<Map<String, Object>> result = new ArrayList<>();
        for (String item : collect.keySet()) {
            Map<String, Object> data = new HashMap<>();
            data.put("name", item);
            data.put("id", collect.get(item));
            result.add(data);
        }
        return result;
    }

    @Override
    public boolean repeat(String siteName) {
        List<Site> sites = this.list(new QueryWrapper<Site>().lambda().eq(Site::getName, siteName).eq(Site::getIsDeleted, 0));
        return sites.size() > 0;
    }

    @Override
    public List<Site> countOverweightNum(Integer offset, List<Long> companyIds) {

        String time = DateUtil.offsetDay(DateUtil.date(), -offset).toString();
        List<Site> siteList = this.list(new LambdaQueryWrapper<Site>().in(Site::getCompanyId, companyIds).eq(Site::getIsDeleted, 0));
        if (ObjectUtil.isEmpty(siteList))
            return siteList;
        List<Long> siteIds = siteList.stream().map(Site::getId).collect(Collectors.toList());
        CheckRecordDto checkRecordDto = new CheckRecordDto()
                .setSiteIds(siteIds)
                .setStartTime(time)
                .setEndTime(DateUtil.now());
        //查询超重的记录
        List<CheckRecord> checkRecordList = this.checkRecordService.getListByCondition(checkRecordDto);
        //按站点id分组
        Map<Long, List<CheckRecord>> map = checkRecordList.stream().collect(Collectors.groupingBy(CheckRecord::getSiteId));
        for (Map.Entry<Long, List<CheckRecord>> entry : map.entrySet()) {
            for (Site site : siteList) {
                if (!site.getId().equals(entry.getKey()))
                    continue;
                //设置超重次数
                site.setOverweightNum(entry.getValue().size());
            }
        }
        return siteList;
    }

    @Override
    public List<Site> getByIds(List<String> siteIds) {
        if (ObjectUtil.isEmpty(siteIds)) return null;
        LambdaQueryWrapper<Site> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(Site::getId, siteIds);
        wrapper.eq(Site::getIsDeleted, CommonConstant.DeleteFlag.NO_DELETE.getCode());
        return siteMapper.selectList(wrapper);
    }
}
